package com.xiaolei.library.Utils;

import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * ByteBuffer 的工具类
 */
public final class ByteBufferUtil
{
    /**
     * 获取2个字节的short
     *
     * @param buffer  缓冲区
     * @param reverse 是否反转读取
     * @return 2个字节的short
     */
    public static short getShort(ByteBuffer buffer, boolean reverse) throws BufferUnderflowException
    {
        ByteOrder oldByteOrder = buffer.order();
        if (reverse)
            buffer.order(oldByteOrder == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
        short value = buffer.getShort();
        if (reverse)
            buffer.order(oldByteOrder);
        return value;
    }

    /**
     * 往缓冲区中写入一个short转换成的2个字节
     *
     * @param buffer  缓冲区
     * @param value   一个short
     * @param reverse 是否反转写入
     */
    public static void putShort(ByteBuffer buffer, short value, boolean reverse) throws UnsupportedOperationException, BufferOverflowException
    {
        ByteBuffer tmpBuffer = ByteBuffer.allocate(Short.SIZE / Byte.SIZE);
        tmpBuffer.order(reverse ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
        tmpBuffer.asShortBuffer().put(value);
        buffer.put(tmpBuffer.array());
        tmpBuffer.clear();
    }

    /**
     * 获取4个字节的int
     *
     * @param buffer  缓冲区
     * @param reverse 是否反转读取
     * @return 4个字节的int
     */
    public static int getInt(ByteBuffer buffer, boolean reverse) throws BufferUnderflowException
    {
        ByteOrder oldByteOrder = buffer.order();
        if (reverse)
            buffer.order(oldByteOrder == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
        int value = buffer.getInt();
        if (reverse)
            buffer.order(oldByteOrder);
        return value;
    }

    /**
     * 往缓冲区中写入一个int转换成的4个字节
     *
     * @param buffer  缓冲区
     * @param value   一个int
     * @param reverse 是否反转写入
     */
    public static void putInt(ByteBuffer buffer, int value, boolean reverse) throws UnsupportedOperationException, BufferOverflowException
    {
        ByteBuffer tmpBuffer = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
        tmpBuffer.order(reverse ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
        tmpBuffer.asIntBuffer().put(value);
        buffer.put(tmpBuffer.array());
        tmpBuffer.clear();
    }

    /**
     * 获取2个字节的char
     *
     * @param buffer  缓冲区
     * @param reverse 是否反转读取
     * @return 2个字节的char
     */
    public static char getChar(ByteBuffer buffer, boolean reverse) throws BufferUnderflowException
    {
        ByteOrder oldByteOrder = buffer.order();
        if (reverse)
            buffer.order(oldByteOrder == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
        char value = buffer.getChar();
        if (reverse)
            buffer.order(oldByteOrder);
        return value;
    }

    /**
     * 往缓冲区中写入一个char转换成的2个字节
     *
     * @param buffer  缓冲区
     * @param value   一个char
     * @param reverse 是否反转写入
     */
    public static void putChar(ByteBuffer buffer, char value, boolean reverse) throws UnsupportedOperationException, BufferOverflowException
    {
        ByteBuffer tmpBuffer = ByteBuffer.allocate(Character.SIZE / Byte.SIZE);
        tmpBuffer.order(reverse ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
        tmpBuffer.asCharBuffer().put(value);
        buffer.put(tmpBuffer.array());
        tmpBuffer.clear();
    }

    /**
     * 获取4个字节的float
     *
     * @param buffer  缓冲区
     * @param reverse 是否反转读取
     * @return 4个字节的float
     */
    public static float getFloat(ByteBuffer buffer, boolean reverse) throws BufferUnderflowException
    {
        ByteOrder oldByteOrder = buffer.order();
        if (reverse)
            buffer.order(oldByteOrder == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
        float value = buffer.getFloat();
        if (reverse)
            buffer.order(oldByteOrder);
        return value;
    }

    /**
     * 往缓冲区中写入一个float转换成的4个字节
     *
     * @param buffer  缓冲区
     * @param value   一个float
     * @param reverse 是否反转写入
     */
    public static void putFloat(ByteBuffer buffer, float value, boolean reverse) throws UnsupportedOperationException, BufferOverflowException
    {
        ByteBuffer tmpBuffer = ByteBuffer.allocate(Float.SIZE / Byte.SIZE);
        tmpBuffer.order(reverse ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
        tmpBuffer.asFloatBuffer().put(value);
        buffer.put(tmpBuffer.array());
        tmpBuffer.clear();
    }

    /**
     * 获取8个字节的float
     *
     * @param buffer  缓冲区
     * @param reverse 是否反转读取
     * @return 8个字节的double
     */
    public static double getDouble(ByteBuffer buffer, boolean reverse) throws BufferUnderflowException
    {
        ByteOrder oldByteOrder = buffer.order();
        if (reverse)
            buffer.order(oldByteOrder == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
        double value = buffer.getDouble();
        if (reverse)
            buffer.order(oldByteOrder);
        return value;
    }

    /**
     * 往缓冲区中写入一个double转换成的8个字节
     *
     * @param buffer  缓冲区
     * @param value   一个double
     * @param reverse 是否反转写入
     */
    public static void putDouble(ByteBuffer buffer, double value, boolean reverse) throws UnsupportedOperationException, BufferOverflowException
    {
        ByteBuffer tmpBuffer = ByteBuffer.allocate(Double.SIZE / Byte.SIZE);
        tmpBuffer.order(reverse ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
        tmpBuffer.asDoubleBuffer().put(value);
        buffer.put(tmpBuffer.array());
        tmpBuffer.clear();
    }
}